class my_model extends uvm_component;
	
	uvm_blocking_get_port#(transaction_dut) port;
	uvm_analysis_port#(transaction_dut) ap;
    sequencer_bus p_sqr;
    reg_model p_rm;

	extern function new(string name, uvm_component parent);
	extern function void build_phase(uvm_phase phase);
	extern virtual task main_phase(uvm_phase phase);
	extern function void invert_tr(transaction_dut tr);

	`uvm_component_utils(my_model);
endclass

function my_model::new(string name, uvm_component parent);
	super.new(name, parent);
endfunction

function void my_model::build_phase(uvm_phase phase);
	super.build_phase(phase);
	port = new("port", this);
	ap = new("ap", this);
endfunction

function void my_model::invert_tr(transaction_dut tr);
    tr.dmac = tr.dmac ^ 48'hFFFF_FFFF_FFFF;
    tr.smac = tr.smac ^ 48'hFFFF_FFFF_FFFF;
    tr.ether_type = tr.ether_type ^ 16'hFFFF;
    tr.crc = tr.crc ^ 32'hFFFF_FFFF;
    for(int i = 0; i < tr.pload.size; i++)
      tr.pload[i] = tr.pload[i] ^ 8'hFF;
endfunction

task my_model::main_phase(uvm_phase phase);
	transaction_dut tr;
	transaction_dut new_tr;
	
    uvm_status_e status;
    uvm_reg_data_t value;
    int length;
    bit[31:0] counter;
    super.main_phase(phase);
    p_rm.invert.read(status, value, UVM_BACKDOOR);
	while(1) begin
		port.get(tr);
		new_tr = new("new_tr");
		new_tr.copy(tr);		
		// `uvm_info("my_model", "get one transaction, copy it:", UVM_LOW)
		// new_tr.print();
		if(value)
            invert_tr(new_tr);
        counter = p_rm.counter.get();
        length = new_tr.pload.size() + 18;
        counter = counter + length;
        p_rm.counter.predict(counter);
        ap.write(new_tr);
	end

endtask

